refactor(agent): remove CherryClaw branding and the Soul Mode toggle#16726
Conversation
…ntry The commit hashes recorded before the rebase onto origin/main are stale; point the entry at the PR instead. Signed-off-by: Vaayne <liu.vaayne@gmail.com>
…n registry design doc The soul-mode entry now lists all PR #16726 commits and documents the interactive-tool overlay removal (agents regain AskUserQuestion, plan-mode, and worktree tools). The declarative-tool-registry design doc gets a status note marking soul de-gating and the claw→cherry-tools merge as landed so its claw/soul references read as history. Signed-off-by: Vaayne <liu.vaayne@gmail.com>
…ntry The commit hashes recorded before the rebase onto origin/main are stale; point the entry at the PR instead. Signed-off-by: Vaayne <liu.vaayne@gmail.com>
…n registry design doc The soul-mode entry now lists all PR #16726 commits and documents the interactive-tool overlay removal (agents regain AskUserQuestion, plan-mode, and worktree tools). The declarative-tool-registry design doc gets a status note marking soul de-gating and the claw→cherry-tools merge as landed so its claw/soul references read as history. Signed-off-by: Vaayne <liu.vaayne@gmail.com>
…n process All agents now run with autonomy enabled, so the soul_enabled branches collapse: claw + agent-memory MCP servers are always injected, the mcp__claw__ auto-approve prefix and allowlist wildcards always apply, AGENT_DISALLOWED_TOOLS (renamed from SOUL_MODE_DISALLOWED_TOOLS) is always spread, and buildSystemPrompt always uses the PromptBuilder workspace prompt (the preset claude_code path became unreachable). AgentTaskService drops the soul/bypassPermissions eligibility gate; the claw config tool no longer reports soul_enabled. Renderer, zod schema, i18n, and CherryClaw branding follow in subsequent commits. Signed-off-by: Vaayne <liu.vaayne@gmail.com>
…schema With soul-mode behavior unconditional in the main process, the flag has no remaining effect: remove the SoulModeField toggle, the soulEnabled form state and its bidirectional coupling with bypassPermissions (permission_mode is now a fully independent setting), the soul-gated composer placeholder branch, the soul_enabled: true seeds on agent creation presets, the scheduled-task agent eligibility filter, and the channels soulModeRequired warning. soul_enabled is removed from the configuration zod schema; the schema is .loose() so stored configs keep parsing with the stale key ignored. Orphaned i18n keys are removed in a follow-up commit. Signed-off-by: Vaayne <liu.vaayne@gmail.com>
…gents engine The former cherryclaw/ directory is the default prompt/heartbeat engine for every agent now, so its three modules (prompt, seedWorkspace, heartbeat) move up into src/main/ai/agents/. Delete the dead seedWorkspaceTemplates and buildToolGuidance paths and simplify composeToolGuidance (claw guidance always applies). De-brand prompt and channel-security wording, drop the CherryClaw docs set and its image, and update architecture doc trees. Kept intentionally: the 'cherry-claw' → 'claude-code' read-time type remap in AgentService and the 'cherry-claw-default' id remap migrator — both are data-migration shims for existing databases. agent.cherryClaw.* i18n keys are renamed in the next commit. Signed-off-by: Vaayne <liu.vaayne@gmail.com>
…rryClaw namespace
Delete the orphaned soul keys (library.config.agent.field.soul_enabled.*,
agent.settings.soulMode.*, the channels soulModeRequired warning, the
obsolete permission_mode.help text, and the unreferenced
agent.cherryClaw soul/sandbox/scheduler/warning/heartbeat groups) and
rename agent.cherryClaw.channels.* / agent.cherryClaw.tasks.* to
agent.channels.* / agent.tasks.* across all twelve locale files, with
code references updated. agent.input.soul_placeholder becomes
agent.input.agent_placeholder (the {{key}} placeholder variant is still
used by the missing-agent composer, so both keys remain). Brand-suffixed
strings like "bypassPermissions (Soul)" are neutralized, and lingering
soul-mode comment references in main are cleaned up.
Adds the breaking-changes entry documenting the removed Autonomous Mode
toggle.
Signed-off-by: Vaayne <liu.vaayne@gmail.com>
…ntry The commit hashes recorded before the rebase onto origin/main are stale; point the entry at the PR instead. Signed-off-by: Vaayne <liu.vaayne@gmail.com>
…verlay Remove AGENT_DISALLOWED_TOOLS (the former soul-mode overlay): agents keep AskUserQuestion, plan-mode, and worktree tools. Cron*, TodoWrite, and NotebookEdit stay blocked regardless — they are classified exposure: 'disabled' in the declarative tool registry, which was always the authoritative layer for them. The assistant role's pre-existing AskUserQuestion disable is restored explicitly. Signed-off-by: Vaayne <liu.vaayne@gmail.com>
Last CherryClaw branding residue: the in-process autonomy MCP server 'claw' becomes 'cherry', so its tools are now mcp__cherry__cron / mcp__cherry__notify / mcp__cherry__config. Registry keys, the auto-approve prefix and allowlist wildcard, condition predicates, prompts (bootstrap + channel security + tool guidance), the agent.tools.builtin.CherryCron i18n label key, and tests follow. Prefix matching keeps the trailing __ delimiter, so mcp__cherry__ and mcp__cherry-tools__ cannot shadow each other; a regression test guards this. Agents whose persisted disabledTools contain the old mcp__claw__cron name lose that override (accepted pre-release). Signed-off-by: Vaayne <liu.vaayne@gmail.com>
Fold the standalone cherry MCP server (cron/notify/config) into cherry-tools so all injected builtin tools live under one server and one mcp__cherry-tools__ namespace. The autonomy handlers move verbatim to cherryAutonomyTools.ts; CherryBuiltinToolsServer registers them only when constructed with a per-session agent context. cron/notify/config join the explicit auto-approve list (they were blanket-allowed as mcp__cherry__* before), while kb_manage keeps its per-call approval. Pre-release break: persisted disabledTools entries using the old mcp__cherry__cron name lose their override; no remap shim added. Signed-off-by: Vaayne <liu.vaayne@gmail.com>
… merge Signed-off-by: Vaayne <liu.vaayne@gmail.com>
The server's only production call site (settingsBuilder) always has the session's agent context, so the optional no-context mode was speculative flexibility with zero users. Make the context required and drop the conditional autonomy-tool registration plus its dead-mode test. Also fix the builtinTools comment: the tool registry hardcodes the runtime names and does not import these constants. Signed-off-by: Vaayne <liu.vaayne@gmail.com>
The branch deleted seedWorkspaceTemplates, leaving only the bootstrap instructions and the SOUL.md content threshold — nothing in the file seeds a workspace anymore. Signed-off-by: Vaayne <liu.vaayne@gmail.com>
…n registry design doc The soul-mode entry now lists all PR #16726 commits and documents the interactive-tool overlay removal (agents regain AskUserQuestion, plan-mode, and worktree tools). The declarative-tool-registry design doc gets a status note marking soul de-gating and the claw→cherry-tools merge as landed so its claw/soul references read as history. Signed-off-by: Vaayne <liu.vaayne@gmail.com>
Soul-mode removal made the soul example prompt ('Help me connect to
Telegram') the placeholder for every agent session, dropping the send
shortcut and slash-search hints. Restore the generic placeholder and
delete the now-orphaned agent.input.agent_placeholder key from all
locales.
Signed-off-by: Vaayne <liu.vaayne@gmail.com>
Signed-off-by: Vaayne <liu.vaayne@gmail.com>
Signed-off-by: Vaayne <liu.vaayne@gmail.com>
Signed-off-by: Vaayne <liu.vaayne@gmail.com>
Signed-off-by: Vaayne <liu.vaayne@gmail.com>
update_channel / remove_channel / reconnect_channel took a raw channel_id and mutated any agent's channel. The config tool is auto-approved and now injected for every agent, so reject foreign channels with the same "not found" error as missing ones (no existence leak). Signed-off-by: Vaayne <liu.vaayne@gmail.com>
The config fields are allowed_chat_ids (allowed_channel_ids on Discord); allow_ids does not exist. Signed-off-by: Vaayne <liu.vaayne@gmail.com>
…hema add_channel validates with ChannelConfigSchema, which requires full feishu/wechat credentials up front — the QR-code-on-omission flow the descriptions promised can never be reached; point QR reconnection at reconnect_channel or the settings UI instead. Also state that enabled defaults to true only on add and is left unchanged when omitted on update. Signed-off-by: Vaayne <liu.vaayne@gmail.com>
Review follow-up — all four findings addressed (
|
Signed-off-by: Vaayne <liu.vaayne@gmail.com> # Conflicts: # src/renderer/pages/settings/__tests__/TasksSettings.test.tsx
AtomsH4
left a comment
There was a problem hiding this comment.
代码审查未发现新的 blocker/warning。
范围:移除 Soul Mode / CherryClaw 品牌和开关,把 autonomy tools、agent-memory、workspace prompt、channel/task eligibility 变为所有 agent 默认能力,并清理相关文档、i18n、settings UI 和测试。
影响:用户不再能按 agent 关闭原 Soul Mode 能力,旧 mcp__claw__* 命名/入口被移除。当前 GitHub merge state 仍是 DIRTY/有冲突,需要先同步 main 解决冲突后再重新确认最终 diff;因此这次先不 approve。
Signed-off-by: Vaayne <liu.vaayne@gmail.com>
kangfenmao
left a comment
There was a problem hiding this comment.
Review summary
Solid, well-tested PR. I found no cross-agent isolation break and no data-loss issue — cross-agent channel/task scoping is defense-in-depth and meaningfully tested, the i18n flattening is complete across all 12 locales, and the guard tests genuinely fail if a guard is removed.
The findings below are refinements, concentrated on one theme: now that every agent can run headless (scheduled / channel dispatch), a few "no interactive responder" stall gaps and an enlarged auto-approve blast radius deserve a second look. None are blockers; #1 is the most clearly actionable.
1. [Medium] Headless runs can still stall on plan-mode / worktree tools
src/main/ai/runtime/claudeCode/settingsBuilder.ts (disallowedTools, ~L835) · src/shared/ai/claudecode/constants.ts
The removed SOUL_MODE_DISALLOWED_TOOLS blocked 9 interactive tools. Only 3 (Cron* / TodoWrite / NotebookEdit) are re-covered by the registry's exposure:'disabled', and AskUserQuestion got a dedicated headless denial — but EnterPlanMode / ExitPlanMode / EnterWorktree (all exposure:'internal') have no headless guard. A scheduled/channel run that enters plan mode waits forever for an approval no one gives — exactly the stall the AskUserQuestion denial was added to prevent. Reads as an oversight rather than an intended widening.
Suggested fix: extend the isHeadless disallow branch to also block EnterPlanMode / ExitPlanMode (and consider EnterWorktree), mirroring the AskUserQuestion treatment.
2. [Medium] Interactive follow-up on a headless-baked warm connection silently loses AskUserQuestion
src/main/ai/runtime/claudeCode/settingsBuilder.ts (baked disallowedTools) + src/main/ai/agentSession/AgentSessionRuntimeService.ts (admitTurn / startNextTurn)
disallowedTools is baked into the SDK query once at connect time, keyed on the connection's headless flag. If an interactive UI message lands on a session while a headless turn is still running, the interactive follow-up rides the same headless-baked connection and never sees AskUserQuestion. The per-turn canUseTool gate can only add denials, not restore a baked-out tool. It self-heals once the session goes fully idle (the connectionHeadless !== headless mismatch rebuild), so the window is "interactive message arriving while a headless turn is busy, then back-to-back follow-ups."
Suggested fix: apply the same headless-mismatch teardown/rebuild at the busy-turn boundary, or drop the baked AskUserQuestion disallow and rely solely on the per-turn canUseTool gate (which already handles both directions symmetrically).
3. [Medium — by design, but broader now] Auto-approved config/cron/notify reachable by untrusted channel input on every agent
src/main/ai/runtime/claudeCode/settingsBuilder.ts (auto-approve prefix) · src/main/ai/mcp/servers/cherryAutonomyTools.ts
A third party who can message the agent over a connected IM channel can, via prompt injection, drive auto-approved config add_channel / remove_channel / rename, cron add, or notify (workspace file exfil to the attacker's chat) with no user approval. This stays correctly scoped to the messaged agent (no cross-agent break), but the PR broadens the surface from opt-in Soul agents to all agents, so the blast radius grew. The accepting comment near the auto-approve prefix acknowledges this.
Suggested mitigation: gate the mutating config actions (add_channel / remove_channel / rename) behind approval even when the read/notify/cron tools stay auto-approved, or deny them when the current turn is headless (mirroring the headless AskUserQuestion denial).
4. [Medium] Proxy-credential redaction — scheme-less edge leak + untested call-site wiring
src/main/ai/runtime/claudeCode/settingsBuilder.ts (redactProxyUrlForAssistantContext, ~L167 and its call site ~L213)
(a) app.proxy.url is free-text. For a scheme-less value like user:pass@host:8080, new URL() does not throw — it parses user: as the scheme, so username/password come back empty, the early return proxyUrl fires, and the raw credential lands in the assistant system prompt. (b) The function is unit-tested in isolation, but no test asserts the assembled context string is actually redacted — deleting the wrapper at the call site leaks credentials with every test still green.
Suggested fix: apply the userinfo-stripping regex unconditionally as a belt (not only in the catch branch), and add a buildClaudeCodeSessionSettings-level test asserting the produced context contains - Proxy: http://host and not the password.
5. [Low] Auto-approve is fail-open for future cherry-tools
src/main/ai/tools/adapters/claudeCode/cherryBuiltinApproval.ts · src/main/ai/tools/adapters/claudeCode/agentTools.ts
Auto-approval is prefix-based (mcp__cherry-tools__) minus a hardcoded kb_manage exception. Any tool later added to the cherry-tools server is auto-approved by default; a future mutating tool ships auto-approved unless the author remembers the exception, and no test would fail.
Suggested fix: invert to an explicit auto-approve allowlist, or add a test that every tool the cherry-tools server registers is classified into exactly one of the two lists. (Prefix shadowing is verified safe — trailing __, no standalone cherry server remains.)
6. [Low] Two one-line test gaps
src/main/ai/runtime/claudeCode/__tests__/buildMcpServers.test.tsonly positively checkscherry-tools/agent-memoryare present; addexpect(Object.keys(result)).not.toContain('skills')to lock in the "defined-but-unwired" invariant the docs describe.src/main/ai/runtime/claudeCode/__tests__/settingsBuilder.test.tsasserts the headless build'sdisallowedToolscontainsAskUserQuestionbut not thatnotifysurvives; addnot.toContain('mcp__cherry-tools__notify').
7. [Low — confirm intended] SKILLS_GUIDANCE prompt block dropped while the skills tool stays injected
src/main/ai/agents/prompt.ts
composeToolGuidance() no longer emits the skills usage guidance, but mcp__skills__skills remains in the registry (exposure:'internal') and its server is still built. The agent keeps the tool but loses all instructions on when/how to use it. Tangential to the "de-brand CherryClaw" scope — please confirm it's intentional.
Nits
- The
configtool renders as "Agent Config" in the edit dialog (agent.tools.builtin.CherryConfig.label) but the hardcoded fallback inMCP_TOOL_LABELSis "Configuration" — same tool, two names. headlessMessageIdscan retain stale ids on a turn-error path (bounded, cosmetic).- The catch-branch redaction regex
[^/@\s]+@leaves a fragment on a malformed URL whose password contains an unencoded@(extreme edge).
Strengths worth calling out
- Cross-agent isolation: every channel-id path validates
channel.agentId === agentIdwith a non-existence-leaking "not found"; delivery re-validates at fire time; rebinds clear stale subscriptions (fail-safe on sync failure); the migrator skips cross-agent legacy rows — all with regression-catching tests (not.toHaveBeenCalledon the downstream mutation, plus a real file-backed integration test). - Headless enforcement: cold / idle-reuse / in-flight-connecting rebuild paths are all correct and individually tested; resume token survives via DB re-hydration;
rollHeadlesssteer semantics are exactly right. No stall gap forAskUserQuestionitself (only the plan-mode siblings in #1). - i18n & docs: renamed keys present in all 12 locales including the dynamic
notify/configtool-card keys; breaking-changes entry matches the final code; tool-registry/data-cluster docs correctly mark skills as unwired and notify/config as user-exposed; no broken links to the deletedcherryclaw/docs.
Review performed read-only against the PR head; no code was changed.
Signed-off-by: Vaayne <liu.vaayne@gmail.com>
There was a problem hiding this comment.
This review was translated automatically.
Reviewed the previously blocking item: PR is no longer in DIRTY/conflict state, all GitHub checks for the current head have completed and passed. Approve.
Original Content
已复核上次阻塞项:PR 已不再是 DIRTY/冲突状态,当前 head 的 GitHub checks 全部完成通过。Approve.
kangfenmao
left a comment
There was a problem hiding this comment.
Follow-up review — after fix(agent-runtime): tighten headless tool guards (64f19ff)
Thanks for the fast turnaround — this commit addresses my earlier review well:
- #1 headless plan-mode/worktree stall → fixed (
HEADLESS_INTERACTIVE_TOOLScoversAskUserQuestion/EnterPlanMode/ExitPlanMode/EnterWorktree). - #2 interactive follow-up losing
AskUserQuestionon a headless-baked warm connection → fixed by dropping the baked headless disallow and enforcing per-turn incanUseTool. - #3 untrusted-channel config mutation → hardened with
headlessConfigMutationHook. - #4 proxy-credential redaction → scheme-less case + assembled-context wiring both covered.
- #5 auto-approve fail-open prefix → switched to an explicit allowlist with a regression test.
- #6 the two missing test assertions → added.
One new gap the refactor introduces, plus one cleanup:
[Medium] Headless interactive-tool denial is skipped under bypassPermissions / acceptEdits
src/main/ai/runtime/claudeCode/settingsBuilder.ts
This commit moved the interactive-tool denial out of disallowedTools and into canUseTool (the per-turn gate). But the SDK skips canUseTool for auto-approved paths — this file's own comment (~L799) states it: "the SDK skips canUseTool for auto-approved paths (bypassPermissions / acceptEdits / default safe-tools), but PreToolUse hooks fire on every tool call regardless of permission mode." That is exactly why the sibling config-mutation guard in this same commit is a PreToolUse hook rather than a canUseTool branch.
Since permissionMode: agentConfig?.permission_mode (L333) passes the user-set mode through unmodified, a scheduled/channel (headless) agent can run in bypassPermissions — which is in fact the mode the old Soul Mode used to force, so migrated autonomy agents plausibly carry it. In that case, for a non-assistant agent, all three enforcement layers miss:
disallowedTools— no longer lists these tools for non-assistant agents (theisHeadlessbranch was removed here),canUseTool— skipped under bypass/acceptEdits,PreToolUsehooks — none registered for the interactive tools (only for config mutation).
Net: AskUserQuestion / EnterPlanMode / ExitPlanMode / EnterWorktree become reachable again in a headless bypass run → the exact stall #1 set out to prevent. This is also a partial regression from the pre-commit state, where the isHeadless branch hard-baked AskUserQuestion into disallowedTools (which does apply under bypass).
Suggested fix: enforce the interactive-tool denial via a PreToolUse hook too (mirroring headlessConfigMutationHook, which fires regardless of permission mode), keeping the canUseTool branch as well so interactive follow-ups can still recover. That makes the two headless guards symmetric and closes the bypass hole without reopening #2.
Worth confirming: whether AskUserQuestion counts as a "default safe-tool" that also skips canUseTool in default mode — if so, the gap is wider than just bypass/acceptEdits.
[Low / cleanup] headless option and the connection-rebuild machinery may now be dead
buildClaudeCodeSessionSettings still accepts headless?: boolean (settingsBuilder.ts:258) but nothing in the function reads it anymore — the baked settings no longer vary by headless. The connectionHeadless mismatch teardown/rebuild in AgentSessionRuntimeService was added specifically because "the AskUserQuestion disallow is settable only at connect time"; that rationale is gone now that enforcement is per-turn. Worth confirming and removing the now-redundant option + rebuild path (and its tests) to avoid leaving dead complexity.
Review performed read-only against the PR head; no code was changed.
Move the headless interactive-tool denial into a PreToolUse hook (headlessInteractiveToolHook) beside the existing canUseTool branch so it also fires under bypassPermissions/acceptEdits, where the SDK skips canUseTool. Without it a migrated autonomy agent running in bypass mode could reach AskUserQuestion/EnterPlanMode/ExitPlanMode/EnterWorktree in a headless scheduled/channel run and stall on a prompt no one answers. With enforcement now fully per-turn (canUseTool + hook, resolved by session id via isCurrentTurnHeadless), the connect-time `headless` plumbing no longer varies any baked setting. Drop the dead path: headless on ClaudeCodeSessionOptions and AgentRuntimeConnectInput, entry.headless / connectionHeadless, and the idle non-headless-connection mismatch rebuild — a warm connection is always safe to reuse now, keeping its resume token. Addresses review of PR #16726 (pullrequestreview-4654207072). Signed-off-by: Vaayne <liu.vaayne@gmail.com>
Signed-off-by: Vaayne <liu.vaayne@gmail.com> # Conflicts: # src/main/ai/agentSession/AgentSessionRuntimeService.ts # src/main/ai/agentSession/__tests__/AgentSessionRuntimeService.test.ts
kangfenmao
left a comment
There was a problem hiding this comment.
LGTM — approving.
All review items across the three rounds are resolved:
- Initial review (#1 headless plan-mode/worktree stall, #2 warm-connection
AskUserQuestionloss, #3 auto-approved config-mutation surface, #4 proxy-credential redaction, #5 fail-open auto-approve prefix, #6 test-assertion gaps) — all fixed. - Follow-up (interactive-tool denial skipped under
bypassPermissions/acceptEdits, plus the now-deadheadlessconnection plumbing) — fixed in5d0b762: the denial is now aPreToolUsehook (fires in every permission mode) beside the retainedcanUseToolbranch, both resolved per-turn by session id viaisCurrentTurnHeadless; the redundant connect-timeheadlessplumbing and mismatch-rebuild were cleanly removed with per-turn enforcement preserved and tests updated.
CI is green (basic-checks, catalog-hand-edit-check, changes, changeset-check, general-test, render-test).
One non-blocking confirmation (not required for merge): the SKILLS_GUIDANCE prompt block was dropped while the mcp__skills__skills tool stays injected — please confirm that leaving the tool available without usage guidance is intentional. Not a merge blocker.
Nice work on the cross-agent scoping and the headless-enforcement hardening.
0xfullex
left a comment
There was a problem hiding this comment.
Requesting changes for five confirmed issues:
-
[Blocking]
settingsBuilder.ts:82andcherryAutonomyTools.ts:769leave bootstrap config writes available in headless turns.HEADLESS_CONFIG_MUTATION_ACTIONSdeniesrenameand channel mutations, butcomplete_bootstrapandreset_bootstrapalso callagentService.updateAgent()to mutateagent.configuration.bootstrap_completed. Since bootstrap instructions explicitly ask the model to callconfig complete_bootstrap, a scheduled or channel run can still mutate agent configuration even though the headless hook says these turns cannot mutate configuration. Please add both bootstrap actions to the headless deny set, or document them as intentional exceptions and adjust the policy/tests. -
[Blocking]
AgentChannelWorkflowService.ts:72loses existing task subscriptions when a channel rebind fails. The code clears subscriptions whenagentIdchanges, then ifsyncChannel()throws it restores the channel row to the old agent and clears subscriptions again. That leaves a failed update with the original channel owner restored but all pre-existingagent_channel_taskrows deleted. Please snapshot and restore the old subscriptions on rollback, or make the rebind and subscription cleanup rollbackable as one operation. -
[Blocking]
AgentTaskService.ts:202can partially update a task when subscription replacement fails.updateJobSchedule()commits the schedule/name/prompt/trigger changes beforereplaceTaskSubscriptions()runs. If subscription replacement throws, the API returns an error but the task fields remain updated while channels remain old.createTaskalready rolls back the registered schedule on this failure path, butupdateTaskhas no equivalent rollback. Please wrap the schedule update and subscription replacement in a single atomic write, or explicitly restore the previous schedule when the subscription write fails. -
[Important]
TasksSettings.tsx:328keeps hidden stalechannelIdsin the task detail state. The UI filters the selector options to channels owned by the task agent, but initializes and resyncschannelIdsfromtask.channelIdswithout filtering. The sharedComboboxkeeps unknown selected values in its controlled array, so when the user changes visible channel selections the PATCH can still include a hidden foreign or missing id. The service now rejects that id, which means the user cannot clear the stale value from this UI. Please normalizechannelIdsagainst the visible/ownedtaskChannelson load and before save. -
[Important]
zh-cn.json:41/zh-tw.json:41andzh-cn.json:661/zh-tw.json:661contain empty user-visible error strings.agent.channels.createError,deleteError,updateError,agent.tasks.error.loadFailed, andagent.tasks.logs.loadErrorare blank in both Chinese locale files while English has real text. The affected toasts and empty states render as blank messages in Chinese. Please fill these migrated locale keys with non-empty localized text.
complete_bootstrap and reset_bootstrap mutate agent.configuration via updateAgent() just like rename/channel actions, but were missing from HEADLESS_CONFIG_MUTATION_ACTIONS, letting scheduled/channel turns flip bootstrap state despite the headless no-config-mutation policy. Signed-off-by: Vaayne <liu.vaayne@gmail.com>
agent.channels.createError/deleteError/updateError, agent.tasks.error.loadFailed and agent.tasks.logs.loadError were empty in zh-CN/zh-TW, rendering blank toasts and empty states. Signed-off-by: Vaayne <liu.vaayne@gmail.com>
channelIds state was fed to the channel Combobox unfiltered, and the Combobox toggles against its controlled array, so ids no longer owned by the task's agent silently rode along in every PATCH — which the service now rejects, leaving the value uncleanable from the UI. Pass a value derived from owned channels so stale ids never reach the selector or the payload. Signed-off-by: Vaayne <liu.vaayne@gmail.com>
…ent fails updateTask committed name/trigger/template changes via updateJobSchedule before replaceTaskSubscriptions ran, so a subscription failure returned an error while leaving the task half-updated. Mirror createTask's rollback: restore the fields the patch touched from the pre-update snapshot, then rethrow. Signed-off-by: Vaayne <liu.vaayne@gmail.com>
…olls back A failed agentId rebind restored the channel row to its original agent but left the pre-existing agent_channel_task rows deleted. Snapshot the subscriptions before clearing and re-subscribe them once the row restore succeeds; only a failed restore keeps them cleared, since the channel may then still point at the new agent. Signed-off-by: Vaayne <liu.vaayne@gmail.com>
|
@0xfullex Thanks for the thorough review — all five findings were real. Fixed in five commits, one per finding:
Verified with the targeted vitest suites plus a full Reflection — why these survived three earlier review rounds: four of the five are edges of previous fixes rather than untouched bugs.
Takeaways we're applying going forward: patch the invariant, not the reviewer's enumeration; sweep symmetric create/update paths when fixing one of them; and when adding validation, check what it does to already-persisted state and the UI that edits it. |
# Conflicts: # src/renderer/i18n/translate/de-de.json # src/renderer/i18n/translate/el-gr.json # src/renderer/i18n/translate/es-es.json # src/renderer/i18n/translate/fr-fr.json # src/renderer/i18n/translate/ja-jp.json # src/renderer/i18n/translate/pt-pt.json # src/renderer/i18n/translate/ro-ro.json # src/renderer/i18n/translate/ru-ru.json # src/renderer/i18n/translate/vi-vn.json
What this PR does
Before this PR:
configuration.soul_enabled). Only soul-enabled agents got the claw/autonomy MCP tools, the agent-memory MCP server, the workspace persona system prompt (SOUL.md / USER.md / FACT.md), and the autonomous-operation disallowed-tools overlay. Enabling it force-switched the agent tobypassPermissions, and scheduled tasks / channels refused agents without it.src/main/ai/agents/cherryclaw/directory (the engine actually powering soul mode for every agent), adocs/references/cherryclaw/doc set, brand mentions in system prompts and channel help text, and anagent.cherryClaw.*i18n namespace.After this PR:
AskUserQuestion, plan-mode, and worktree tools where the tool registry allows them (Cron*/TodoWrite/NotebookEditremain blocked by their pre-existingexposure: 'disabled'registry classification). Exception added after review: headless runs (channel-triggered and scheduled-task dispatches) still disallowAskUserQuestion— they have no responder, so a question would stall the run.configtool now rejects channels owned by another agent;notify/configare user-disableable (exposure: 'user') likecron; agents with non-blank user instructions skip the bootstrap onboarding interview; the prompt no longer references the unmountedmcp__skills__skillstool.soul_enabledflag is fully removed: no UI toggle, no zod schema field, no reads anywhere.permission_modeis now a fully independent setting and its field is always visible in the agent edit dialog.cherryclaw/engine directory is flattened intosrc/main/ai/agents/(prompt / bootstrap / heartbeat), prompts and channel help are de-branded, the CherryClaw doc set is deleted, andagent.cherryClaw.channels.*/agent.cherryClaw.tasks.*i18n keys are flattened toagent.channels.*/agent.tasks.*across all locales.clawMCP server is merged intocherry-tools; autonomy tools now live undermcp__cherry-tools__cron,mcp__cherry-tools__notify, andmcp__cherry-tools__config.seedWorkspaceTemplates,PromptBuilder.buildToolGuidance, and the always-true branches ofcomposeToolGuidance/adjustAllowedToolsForMcp.Fixes # N/A
Why we need it and why it was done in this way
CherryClaw's autonomy features were productized as soul mode and recent work already made personality + autonomy the default for new agents. Keeping a toggle (and a brand) for behavior that every agent should have added a second code path, a confusing permission-mode coupling, stale docs, and tool-name drift. Removing the flag and merging the autonomy tools into
cherry-toolsgives the app one agent behavior instead of two.The following tradeoffs were made:
AskUserQuestion, plan-mode, and worktree tools stay available to every agent unless the tool registry disables them. The assistant role's pre-existingAskUserQuestiondisable is preserved explicitly, and headless (channel / scheduled-task) runs keepAskUserQuestiondisallowed via a transient dispatch flag.'cherry-claw'→'claude-code'read-time type remap inAgentServiceand the'cherry-claw-default'id remap migrator. The unrelatedcherry-claw.pngmodel icon is untouched.soul_enabledconfiguration key is simply ignored (the configuration zod schema is.loose()), so no data migration is needed.mcp__claw__*) are not kept as aliases; callers must use the newmcp__cherry-tools__*names.The following alternatives were considered:
cherryclaw/toworkspace/orpersona/instead of flattening — rejected:workspaceis heavily overloaded in this codebase and the directory only held a few agent-engine modules.clawMCP server name as a compatibility alias — rejected: this PR removes the CherryClaw product surface rather than preserving a legacy synonym.Links to places where the discussion took place: N/A
Breaking changes
The Soul Mode / Autonomous Mode toggle is removed from agent settings; every agent now always runs with autonomy features (scheduled tasks, channels, cron/notify/config tools, agent-memory tools, workspace persona prompt). Scheduled tasks and channels no longer require Soul Mode or
bypassPermissions.MCP tool names changed from
mcp__claw__*tomcp__cherry-tools__*:mcp__claw__cron→mcp__cherry-tools__cronmcp__claw__notify→mcp__cherry-tools__notifymcp__claw__config→mcp__cherry-tools__configDocumented in
v2-refactor-temp/docs/breaking-changes/2026-07-03-remove-soul-mode-toggle.md; no user data migration is required.Special notes for your reviewer
mcp__claw__*is acceptable, whether all Claude Code Agents should default to autonomy tools, and whether the preserved assistant-roleAskUserQuestionspecial case is still correct.git logshows the moved engine files as renames (cherryclaw/prompt.ts→agents/prompt.ts, etc.) — review with rename detection on.pnpm lint,pnpm test, andpnpm build:checkpass locally. GitHub CI is green:changes,catalog-hand-edit-check,changeset-check,basic-checks,general-test, andrender-testpassed (notifyskipped).Checklist
This checklist is not enforcing, but it's a reminder of items that could be relevant to every PR.
Approvers are expected to review this list.
mainfor active development,v1for v1 maintenance fixes/gh-pr-review,gh pr diff, or GitHub UI) before requesting review from othersRelease note